
#include "stdafx.h"
#include "cpuinfo.h"

DWORD GetCpuCaps(VOID)
{
	DWORD cc;

	__asm
	{
		xor edi, edi

		pushfd
		pop eax             //eax = eflags
		mov ebx, eax
		xor eax, 00200000h  //toggle bit 21, eflags.[ID]
		push eax
		popfd
		pushfd
		pop eax
		xor eax, ebx
		jz done
		or edi, CC_CPUID_MASK

		mov eax, 00000000h
		cpuid
		test eax, eax
		jz done

		mov eax, 00000001h
		cpuid

		//test_x87:
		test edx, 00000001h
		jz test_mmx
		or edi, CC_X87_MASK

test_mmx:
		test edx, 00800000h // Is IA MMX technology bit (Bit 23 of EDX) set?
		jz test_sse // MMX_Technology_Found
		or edi, CC_MMX_MASK

test_sse:
		test edx, 02000000h
		jz test_sse2
		or edi, CC_SSE_MASK

test_sse2:
		test edx, 04000000h
		jz test_sse3
		or edi, CC_SSE2_MASK

test_sse3:
		test ecx, 00000001h
		jz test_ssse3
		or edi, CC_SSE3_MASK

test_ssse3:
		test ecx, 00000200h
		jz test_sse4_1
		or edi, CC_SSSE3_MASK

test_sse4_1:
		test ecx, 00080000h
		jz test_sse4_2
		or edi, CC_SSE4_1_MASK

test_sse4_2:
		test ecx, 00100000h
		jz amd_test
		or edi, CC_SSE4_2_MASK

amd_test:
		mov eax, 80000000h
		cpuid
		cmp eax, 80000000h
		jbe done

		mov eax, 80000001h
		cpuid

//test_3dnow:
		test edx, 80000000h
		jz test_3dnowx
		or edi, CC_3DNOW_MASK

test_3dnowx:
		test edx, 40000000h
		jz test_mmxx
		or edi, CC_3DNOWX_MASK

test_mmxx:
		test edx, 00400000h
		jz done
		or edi, CC_MMXX_MASK

done:
		mov cc, edi
	}

	return cc;
}

#if 0
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	DWORD cc = GetCpuCaps();

	if (cc & CC_CPUID_MASK)
	cout << "cpuid" << endl;
	if (cc & CC_X87_MASK)
	cout << "x87" << endl;
	if (cc & CC_MMX_MASK)
	cout << "mmx" << endl;
	if (cc & CC_SSE_MASK)
	cout << "sse" << endl;
	if (cc & CC_SSE2_MASK)
	cout << "sse2" << endl;
	if (cc & CC_SSE3_MASK)
	cout << "sse3" << endl;
	if (cc & CC_SSSE3_MASK)
	cout << "ssse3" << endl;
	if (cc & CC_SSE4_1_MASK)
	cout << "sse4.1" << endl;
	if (cc & CC_SSE4_2_MASK)
	cout << "sse4.2" << endl;
	if (cc & CC_3DNOW_MASK)
	cout << "3dnow!" << endl;
	if (cc & CC_3DNOWX_MASK)
	cout << "3dnow! extension" << endl;
	if (cc & CC_MMXX_MASK)
	cout << "mmx extension" << endl;


	getchar();
	return 0;
}
#endif
